package com.yyfax.pay.common.aspect;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

import com.yyfax.framework.exception.YYException;
import com.yyfax.framework.yyfax.enums.RspCodeEnum;
import com.yyfax.framework.yyfax.enums.YesNoEnum;
import com.yyfax.pay.common.constants.PayConstants;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.common.model.to.YYPayApiReq;
import com.yyfax.pay.common.model.to.YYPayApiReq2;
import com.yyfax.pay.common.model.to.YYPayParams;
import com.yyfax.pay.common.util.CheckSignUtils;
import com.yyfax.pay.config.data.service.MerchantConfigService;
import com.yyfax.pay.config.model.po.MerchantConfigPO;

public class CheckSignAspect {
	@Autowired
	private MerchantConfigService merchantConfigService;

	@Autowired
	private PayConstants payConstants; // 支付配置类

	public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
		// 方法参数校验
		MethodSignature ms = (MethodSignature) pjp.getSignature();
		Object[] args = pjp.getArgs();
		for (int i = 0; i < args.length; i++) {
			Object param = args[i];

			// 新增类型YYPayApiReq2，后面需要替换YYPayApiReq
			if (YYPayApiReq2.class.isAssignableFrom(args[0].getClass())) {
				YYPayApiReq2<?> req = (YYPayApiReq2) param;
				Object p = req.getParams();
				String merchantCode = req.getMerchantCode();
				checkSign(p, merchantCode, req.getSign());
			}

			if (YYPayApiReq.class.isAssignableFrom(args[0].getClass())) {
				YYPayApiReq req = (YYPayApiReq) param;
				Object p = req.getParams();
				String merchantCode = (String) p.getClass().getDeclaredMethod("getMerchantCode").invoke(p);
				check((YYPayParams) p, merchantCode, req.getSign());
			}

			if (YYPayParams.class.isAssignableFrom(args[0].getClass())) {
				YYPayParams p = (YYPayParams) args[0];
				check(p, null, p.getSign());
			}

		}
		Object retVal = pjp.proceed();
		return retVal;
	}

	private void check(YYPayParams param, String merchantCode, String signValue) throws Exception {
		// param.validate();
		String signKey = null;
		if (StringUtils.isBlank(merchantCode)) {
			signKey = payConstants.getSignKey();
		} else {
			MerchantConfigPO merchantConfigPO = merchantConfigService.queryByMerchantCode(merchantCode);
			if (merchantConfigPO == null || !YesNoEnum.YES.isValue(merchantConfigPO.getState())) {
				throw new YYException(PayRspCodeEnum.PAY_CODE_MERCHANT_NOT_EXISTS, "商户：" + merchantCode + "信息不存在");
			}
			signKey = merchantConfigPO.getSignKey();
		}
		boolean result = CheckSignUtils.checkSign(param, signKey, signValue);
		if (!result) {
			throw new YYException(RspCodeEnum.COMMON_ERROR_NO_SIGN_AUTHENTICATION);
		}
	}

	/**
	 * 校验签名
	 * 
	 * @author buyi
	 * @date 2017-05-24 10:31:34
	 * @since v1.0.0
	 * @param p
	 * @param merchantCode
	 * @param srcSign 原签名串
	 * @throws Exception
	 */
	private void checkSign(Object p, String merchantCode, String srcSign) throws Exception {
		String key = null;
		if (StringUtils.isBlank(merchantCode)) {
			key = payConstants.getSignKey();
		} else {
			MerchantConfigPO merchantConfigPO = merchantConfigService.queryByMerchantCode(merchantCode);
			if (merchantConfigPO == null || !YesNoEnum.YES.isValue(merchantConfigPO.getState())) {
				throw new YYException(PayRspCodeEnum.PAY_CODE_MERCHANT_NOT_EXISTS, "商户：" + merchantCode + "信息不存在,或者状态为无效", "无效请求");
			}
			key = merchantConfigPO.getSignKey();
		}

		boolean result = CheckSignUtils.checkSign2(p, key, srcSign);

		if (!result) {
			throw new YYException(RspCodeEnum.COMMON_ERROR_NO_SIGN_AUTHENTICATION, "签名不通过：" + p, "无效请求");
		}

	}

}
